package com.example.config;

import com.example.entity.Permission;
import com.example.handler.MyAuthenticationFailureHandler;
import com.example.handler.MyAuthenticationSuccessHandler;
import com.example.mapper.PermissionMapper;
import com.example.mapper.UserMapper;
import com.example.security.MyUserDetailService;
import com.example.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

/**
 *   Security  配置
 *   WebSecurityConfigurerAdapter 帮我们默认配置了认证方法
 */

@Component
@EnableWebSecurity       //开启过滤器  拦截所有的请求
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private MyAuthenticationFailureHandler failureHandler;
    @Resource
    private MyAuthenticationSuccessHandler successHandler;
    @Resource
	private MyUserDetailService myUserDetailService;
    @Resource
	private UserMapper userMapper;
    @Resource
	private PermissionMapper permissionMapper;

	// 配置认证用户信息和权限
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//		// 设置用户账号信息和权限,此处设置的默认值  用户信息应该从数据库中获取
//		auth.inMemoryAuthentication().withUser("admin").password("123456").authorities("addOrder","showOrder","deleteOrder","updateOrder");
//		// user 只有查看订单权限
//		auth.inMemoryAuthentication().withUser("user").password("123456").authorities("showOrder","addOrder");

		//获取数据库中的数据进行验证用户信息,passwordEncoder() 加密方法
		auth.userDetailsService(myUserDetailService).passwordEncoder(new PasswordEncoder() {

			//加密的密码与数据库中的密码进行对比,charSequence 表单提交密码，encodedPassWord 数据库密码
			public boolean matches(CharSequence charSequence, String encodedPassWord) {
			    String pass=MD5Util.encode((String) charSequence);   // 对表单提交过来的密码进行加密
				System.out.println("表单提交密码:"+charSequence+",数据库密码:"+encodedPassWord+",表单加密之后的密码:"+pass);
				return MD5Util.encode((String) charSequence).equals(encodedPassWord);
			}

			// charSequence 对表单密码进行加密
			public String encode(CharSequence charSequence) {
				System.out.println("charSequence:"+charSequence);
				return MD5Util.encode((String) charSequence);
			}


		});

	}

	// 配置HttpSecurity 拦截资源
	protected void configure(HttpSecurity http) throws Exception {
	    //如何权限控制： 给每一个请求路径 分配一个权限名称 然后让每一个账号关联该名称，就可以实现权限控制


	    //   /** 表示拦截所有请求   .httpBasic();浏览器认证方式  formLogin();表单认证模式
//		http.authorizeRequests()
//                // 配置查询订单权限
//                .antMatchers("/login").permitAll()   //放行 登录页面
//                 .antMatchers("/showOrder").hasAnyAuthority("showOrder")
//                 .antMatchers("/addOrder").hasAnyAuthority("addOrder")
//                 .antMatchers("/deleteOrder").hasAnyAuthority("deleteOrder")
//                 .antMatchers("/updateOrder").hasAnyAuthority("updateOrder")
//                .antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login")
//                .successHandler(successHandler).failureHandler(failureHandler)  //登录认证方法
//                .and().csrf().disable();  //loginPage 使用自定义页面   .and().csrf().disable()  禁用csrf(跨站点攻击) 否则请求中需要传入token

		// 从数据库中获取
		ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry authorizeRequests = http.authorizeRequests();
		// 1.读取数据看权限列表
		List<Permission> permissionList=permissionMapper.findAllPermission();
		for (Permission permission : permissionList) {
			// 2. 设置权限
			authorizeRequests.antMatchers(permission.getUrl()).hasAnyAuthority(permission.getPermTag());
		}
		// 3. 放行登录请求,antMatchers("/login").permitAll() 所有请求都可以访问/login,.antMatchers("/**") 拦截所有请求，.formLogin().loginPage("/login") 登录模式 和登录页面
		authorizeRequests.antMatchers("/login").permitAll()
				.antMatchers("/**").fullyAuthenticated().and().formLogin().loginPage("/login")
				.failureHandler(failureHandler).successHandler(successHandler)
				.and().csrf().disable();
	}

    @Bean
    public static NoOpPasswordEncoder passwordEncoder() {
        return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
    }

}